package cn.fansunion.leecode.linkedlist;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 删除有序数组中的重复项
 * 给你一个有序数组 nums ，请你 原地 删除重复出现的元素，使每个元素 只出现一次 ，返回删除后数组的新长度。

不要使用额外的数组空间，你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @author wen.lei@brgroup.com
 *
 *         2022-1-6
 */
public class RemoveDuplicatesFromSortedArray {

    public static void main(String[] args) {
        RemoveDuplicatesFromSortedArray rdfsa = new RemoveDuplicatesFromSortedArray();
        // test1
        int[] nums1 = new int[] {1, 1, 2, 2, 3, 3, 4, 5, 5, 8};
        int length1 = rdfsa.removeDuplicates(nums1);
        for (int index = 0; index < length1; index++) {
            System.out.print(nums1[index] + ",");
        }
        System.out.println();
        // test2
        int[] nums2 = new int[] {1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9};
        int length2 = rdfsa.removeDuplicates(nums2);
        for (int index = 0; index < length2; index++) {
            System.out.print(nums2[index] + ",");
        }
        System.out.println();
        System.out.println(rdfsa.removeDuplicatesList(nums2));
        System.out.println(rdfsa.removeDuplicatesSet(nums2));
    }

    /**
     * 参考网友和官方答案，使用“双指针”解法
     * 问题的本质：不重复的元素向前移动，覆盖前面重复的元素
     * 思维困境：总是在判定元素的重复,类似：nums[index] == nums[index - 1]
     * @param nums
     * @return
     */
    public int removeDuplicates(int[] nums) {
        //特殊情况判断
        if (nums==null || nums.length == 0) {
            return 0;
        }
        //
        int fastIndex = 1;
        int slowIndex = 1;
        //问题的本质：不重复的元素向前移动，覆盖前面重复的元素
        //思维困境：总是在判定元素的重复,类似：nums[index] == nums[index - 1]
        for (fastIndex = 1; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != nums[fastIndex - 1]) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
    
    /**
     * 使用list，仅仅是为了获得长度。可以考虑返回list
     * @param nums
     * @return
     */
    public int removeDuplicatesList(int[] nums) {
        //特殊情况判断
        if (nums==null || nums.length == 0) {
            return 0;
        }
        List<Integer> list = new ArrayList<>();
        for (int num : nums) {
            if(!list.contains(num)) {
                list.add(num);
            }
        }
        return list.size();
    }
    
    /**
     * 使用set，仅仅是为了获得长度。可以考虑返回set，顺序丢失了
     * @param nums
     * @return
     */
    public int removeDuplicatesSet(int[] nums) {
        //特殊情况判断
        if (nums==null || nums.length == 0) {
            return 0;
        }
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            set.add(num);
        }
        return set.size();
    }
}
